/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dlc.buscador;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import dlc.modelo.Palabra;
import dlc.modelo.Posteo;
import dlc.modelo.Vocabulario;
import dlc.persistencia.BaseDatos;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class Buscador {

    private String consulta;
    private LinkedList<String> terminos;
    private HashMap<String, Valoracion> valoracion;
    private Vocabulario voc = null;
    private int cantidadDocumentos; //cantidad total de documentos
    private String textoArchivo = "";//para guardar el texto de los archivos donde hay información

    public Buscador() throws Exception {
        
        this.valoracion = new HashMap<String, Valoracion>();
        this.voc = Vocabulario.getInstance();
        System.out.println("Vocabulario tiene palabras: " + voc.getTerminos().size());
        cantidadDocumentos = getTotalDocs();

    }

    private int getTotalDocs() throws Exception {

        BaseDatos dao = new BaseDatos(2);
        return dao.obtenerTotalDocuemtos();

    }

    private void procesarConsulta() {
        String consultaLimpia = Utils.limpiarAcentos(consulta);
        terminos = Utils.separarPalabras(consultaLimpia);
    }

    public void setConsulta(String consulta) {
        this.consulta = consulta;
    }

    public String getConsulta() {
        return consulta;
    }

    public LinkedList<String> getTerminos() {
        return terminos;
    }

    public void setTerminos(LinkedList<String> terminos) {
        this.terminos = terminos;
    }

    public Resultado[] buscar(String consulta) throws Exception {
        this.consulta = Utils.limpiarAcentos(consulta);
        Valoracion[] valoraciones = this.buscarValoraciones();
        Resultado[] resultadosArray = new Resultado[valoraciones.length];

        int i = 0;
        for (Valoracion val : valoraciones) {
            Resultado r = new Resultado(val.getDocumento().getNombre(),
                    buscarURLWiki(val.getDocumento().getPath()),
                    val.getDocumento().getPath(),
                    buscarTextoResultado());
            resultadosArray[i] = r;
            i++;
        }

        return resultadosArray;
    }

    private String buscarTextoResultado() {
        String caracteresPagina = Utils.limpiarAcentos(this.textoArchivo);
        LinkedList<String> listaPalabras = Utils.separarPalabras(caracteresPagina);

        String e = "";
        for (int index = 0; index < listaPalabras.size(); index++) {
            if (listaPalabras.get(index).compareTo(this.consulta) == 0) {
                e = e + "...";
                for (int j = index - 5; j < index + 5; j++) {
                    if (j > 0) {
                        String k = listaPalabras.get(j);
                        e = e + " " + k;
                    } else {
                        String k = listaPalabras.get(0);
                        e = e + " " + k;
                    }
                }
                e = e + "...\n";
            }

        }
        return e;
    }

    private String buscarURLWiki(String path) throws Exception {

        File f = new File(path);
        String urlWiki = "";
        String textoPagina = "";

        FileReader docTxt = new FileReader(f);
        BufferedReader br = new BufferedReader(docTxt);

        boolean ban = true;
        while (br.ready()) {
            textoPagina = br.readLine();
            if (ban) {
                urlWiki = textoPagina;
                ban = false;
            }
            this.textoArchivo = this.textoArchivo + textoPagina;
        }

        return urlWiki;
    }

    private Valoracion[] buscarValoraciones() throws Exception {
        procesarConsulta();

        BaseDatos dao = new BaseDatos(2);

        for (String termino : terminos) {

            Palabra palabra = voc.getPalabra(termino);
            if (palabra != null) {
                ArrayList<Posteo> posteoList = new ArrayList<Posteo>();

                posteoList = dao.armarPosteos(posteoList, palabra);

                //Recorrer posteos armados de esa palabra e ir armando los objetos Valoracion (new Valoracion())
                for (Posteo posteo : posteoList) {
                    Valoracion val = valoracion.get(posteo.getDocumento().getNombre());

                    if (val != null) {
                        val.incrementarCantTerminosDeConsultaEnDoc(); //Revisar si con "val" afecto al mismo objeto que el anterior (en teoría si)
                    } else {
                        val = valoracion.put(posteo.getDocumento().getNombre(), new Valoracion(posteo.getDocumento()));
                    }

                    val = valoracion.get(posteo.getDocumento().getNombre());

                    val.setValoracion(val.getValoracion()
                            + (((double) 1 - (double) palabra.getCantDoc() / (double) cantidadDocumentos)
                            * (double) posteo.getTf()));
                }
            }
        }

        //Normalizar pesos - Comentado ya que no tengo los archivos en Disco y en tal caso Valoración pasará a valer "cualquier churro"

        for (Map.Entry<String, Valoracion> valor : valoracion.entrySet()) {
            System.out.println("Antes: " + valor.getValue().getValoracion());
            valor.getValue().setValoracion(valor.getValue().getValoracion() * valor.getValue().getCantTerminosDeConsultaEnDoc()
                    / valor.getValue().getDocumento().getCantPalabras()); //getLongitud() debería devolver el tamaño del archivo en disco...
            System.out.println("Despues: " + valor.getValue().getValoracion());
        }

        //Valoracion[] valoracionArray = (Valoracion[]) valoracion.values().toArray(); //PORQUE NO FUNCA ASI?

        Collection<Valoracion> valoracionCollection = valoracion.values();
        Valoracion[] valoracionArray = new Valoracion[valoracionCollection.size()];
        int i = 0;
        for (Valoracion val : valoracionCollection) {
            valoracionArray[i] = val;
            i++;
        }

        Ordenador ordenador = new Ordenador(valoracionArray);
        ordenador.ordenar();

        return valoracionArray;
    }
}